#include "terrianGLSL.h"
#include "GL/glut.h"

#include <cmath>
#include <iostream>
#include <strstream>
#include <vector>

using namespace std;

#include "demDataLoad.h"

const float AppGloble::PI=3.1416f;
float AppGloble::crateUniformShader = 0.5;
float AppGloble::axlength = 5.0f;

bool AppGloble::drawFillMode = true;
bool AppGloble::usingLigting = true;

int AppGloble::frameRendered=0;		//记录帧率
int AppGloble::curFPS=0; 

GLuint AppGloble::theVShader=0;		//vs代码段
GLuint AppGloble::thePShader=0;		//ps代码段
GLuint AppGloble::prgrm=0;			//可用于替换固定流水线的glsl 代码段

//GLint AppGloble::crealLoc=0;
//GLint AppGloble::cvirtLoc=0;
//float AppGloble::crealVal=0;
//float AppGloble::cvirtVal=0;

GLint AppGloble::crateLoc=0;
GLint AppGloble::terrainTexloc=0;
GLint AppGloble::colorTexloc=0;
GLint AppGloble::maxHightloc=0;
GLint AppGloble::eyeposloc=0;
GLint AppGloble::isDetailloc=0;
GLint AppGloble::renderSizexLoc=0;
GLint AppGloble::renderSizeyLoc=0;
GLint AppGloble::isColorTexUseloc=0;

GLint AppGloble::isColorTexUse=1;//1 use 0 not
GLint AppGloble::isDetail=0;

float AppGloble::maxHightValue=15000.0f;

GLuint AppGloble::fuzuCallListNum = 0;
GLuint AppGloble::terrainCallListNum = 0;
GLuint AppGloble::terrainDetailCallListNum = 0;
GLuint AppGloble::terrainMoreDetailCallListNum=0;


GLuint AppGloble::textureNUM = 0;
GLuint AppGloble::terrianTextureNUM = 0;

GLuint AppGloble::tmpTextureNUM = 0;

bool AppGloble::ldown = false;
int AppGloble::mdownXpos = 0;
int AppGloble::mdownYpos = 0;
float AppGloble::oldLong = 0.0f;
float AppGloble::oldLat = 0.0f;

bool AppGloble::rdown = false;
float AppGloble::oldRadius = 0.0f;

bool AppGloble::usingGLSL20 = true;
bool AppGloble::detailPrint = false;

unsigned int AppGloble::mapSizex = 2048;
unsigned int AppGloble::mapSizey = 2048;

float AppGloble::renderSizex = 4.0f;
float AppGloble::renderSizey = 4.0f;

long AppGloble::totalTriCount = 0;

bool AppGloble::coordAxixNeed = true;
bool AppGloble::sceneInfNeed = true;
bool AppGloble::usingColorTex = true;

eyePosition AppGloble::noweye;

int AppGloble::detailGridNum = 256;

int AppGloble::roamDividDepth=16;

float AppGloble::eyetox=0.0f;

float AppGloble::eyetoy=0.0f;

float AppGloble::crateValue=0.5f;

void drawModel_terrain()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);		// Clear Screen And Depth Buffer

	if(AppGloble::usingGLSL20)
	{
		glEnable(GL_TEXTURE_2D);
		//glBindTexture(GL_TEXTURE_2D, AppGloble::terrianTextureNUM);     // Bind To The Texture ID
		glUseProgram(AppGloble::prgrm);	
		
		if(AppGloble::noweye.eyex>0.0f 
		   && AppGloble::noweye.eyex<AppGloble::renderSizex 
		   && AppGloble::noweye.eyey>0.0f 
		   && AppGloble::noweye.eyey<AppGloble::renderSizey
		   && abs(AppGloble::noweye.eyez)<min(AppGloble::renderSizey/2.0f, AppGloble::renderSizex/2.0f)
		   )
		{
			//*
			glEnable(GL_STENCIL_TEST);
			//bool tmpb = glIsEnabled(GL_STENCIL_TEST);			
			glStencilFunc(GL_ALWAYS,0x01,0x01);
			glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);		
			//*/		

			AppGloble::isDetail = 1;
			glUniform1i(AppGloble::isDetailloc, AppGloble::isDetail);

			if(abs(AppGloble::noweye.eyez)<min(AppGloble::renderSizey/4.0f, AppGloble::renderSizex/4.0f))
			{
				glCallList(AppGloble::terrainMoreDetailCallListNum);				
			}
			else
			{
				glCallList(AppGloble::terrainDetailCallListNum);				
			}

			//*
			glStencilFunc(GL_GREATER,0x01,0x01);
			//glStencilFunc(GL_GREATER,0,0x1);
			glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
			//*/

			glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
			glEnable(GL_BLEND);

			AppGloble::isDetail = 0;
			glUniform1i(AppGloble::isDetailloc, AppGloble::isDetail);
			glCallList(AppGloble::terrainCallListNum);			
			
			glDisable(GL_STENCIL_TEST);
			glDisable(GL_BLEND);
		}		
		else 
		{			
			AppGloble::isDetail = 0;
			glUniform1i(AppGloble::isDetailloc, AppGloble::isDetail);
			glCallList(AppGloble::terrainCallListNum);			
		}

		glUseProgram(0);
		glDisable(GL_TEXTURE_2D);
	}
	else
	{	
		glCallList(AppGloble::terrainCallListNum);
	}

	if(AppGloble::coordAxixNeed)
	{
		drawCoordAxis();
	}

	if(AppGloble::sceneInfNeed)
	{
		showScenInf();
	}

	glutSwapBuffers();

	++AppGloble::frameRendered;
}

//
int main(int argc, char** argv)
{
	//*
	demo_Mandelbrot();
	//demo_twoPass();
	return 0;
	//*/

	glutInit(&argc, argv);
	//创建窗口
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL | GLUT_ALPHA);	

	glutInitWindowSize(800,600);

	glutInitWindowPosition(100,100);

	glutCreateWindow("Terrian Zjn PBR GLSL");

	int tmpMaxValue;
	glGetIntegerv(GL_MAX_TEXTURE_SIZE,&tmpMaxValue);

	//int themaxtsize;
	glGetIntegerv(GL_MAX_TEXTURE_UNITS,&tmpMaxValue);

	//Dem_Area* theDA = new Dem_Area("e:\\World_DEM_from_sx\\e100n40\\E100N40.DEM", 1024, 1024, 0);
	//Dem_Area* theDA = new Dem_Area("e:\\World_DEM_from_sx\\e060n40\\E060N40.DEM", AppGloble::mapSizex, AppGloble::mapSizey, 0);
	//Dem_Area* theDA = new Dem_Area("f:\\world_dem_data\\e100n40\\E100N40.DEM", AppGloble::mapSizex, AppGloble::mapSizey, 0);
	Dem_Area* theDA = new Dem_Area("./e060n40/E060N40.DEM", AppGloble::mapSizex, AppGloble::mapSizey, 0);

	//theDA->smooth(0.75f, 5);

	theDA->load_dem_file_avr();

	//设置opengl状态机
	//glClearColor(0.2, 0.4, 0.6, 1.0);	
	glClearColor(1.0, 1.0, 1.0, 0.0);	

	glClearStencil(0x0);

	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_TEST);

	glCullFace(GL_FRONT_AND_BACK);
	glShadeModel(GL_SMOOTH);

	//AppGloble::noweye.eyez=	AppGloble::noweye.eyey=0.0f;
	//AppGloble::noweye.eyex=9.0f;

	//AppGloble::noweye.radius=0.9;
	//AppGloble::noweye.longitude=0.0f;
	//AppGloble::noweye.latitude = 0.0f;	

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, 1.0, 0.1, 1000.0);	//第三个参数,近裁减面,不能为0

	
	//glColor3f(1.0f,1.0f,1.0f);

	detailTerrainGridCreate();

	moreDetailTerrainGridCreate();

	//lightAndMatSet();

	//初始化GLSL环境
	//*
	glewInit();
	if (glewIsSupported("GL_VERSION_2_0"))
	{
		std::cout<<std::endl<<"Ready for OpenGL 2.0"<<std::endl;

		//float* tmpp = (float*)theDA->get_dem_data();
		texSet_terrian(theDA->get_dem_data());

		//temDemDatap = (int*)theDA->get_dem_data();

		if(!shaderSet_terrian())		
		{			
			AppGloble::usingGLSL20 = false;
			std::cout<<std::endl<<"fail to do shaderSet_terrian"<<std::endl;		
		}
	}	
	else 
	{
		AppGloble::usingGLSL20 = false;
		std::cout<<std::endl<<"penGL 2.0 not supported"<<std::endl;		
	}

	if(AppGloble::usingGLSL20)
	{
		//terrianGridCreate_();
		if(false)
		{
			trangleFansTerrainGridCreate(theDA->load_dem_file_avr(AppGloble::mapSizex,AppGloble::mapSizey),
			AppGloble::mapSizex,
			AppGloble::mapSizey);
		}
		if(true)
		{
		RoamTrianglesCreate(theDA->load_dem_file_avr(AppGloble::mapSizex,AppGloble::mapSizey),
			AppGloble::mapSizex,
			AppGloble::mapSizey,
			AppGloble::renderSizex,
			AppGloble::renderSizey);
		}

		if(false)
		{
		if(!nonUniformTerrainGridCreate(theDA->load_dem_file_avr(AppGloble::mapSizex,AppGloble::mapSizey),
			AppGloble::mapSizex,
			AppGloble::mapSizey,
			AppGloble::renderSizex,
			AppGloble::renderSizey))
		{
			std::cout<<"fail to create terrian grid"<<std::endl;	

			delete theDA;
			int pp;
			cin>>pp;
			return 0;
		}
		}
	}
	else
	{
		if(false)
		{
			trangleFansTerrainGridCreate(theDA->load_dem_file_avr(AppGloble::mapSizex,AppGloble::mapSizey),
				AppGloble::mapSizex,
				AppGloble::mapSizey);

			if(false)
			{
				if(!nonUniformTerrainGridCreate(theDA->load_dem_file_avr(AppGloble::mapSizex,AppGloble::mapSizey),
					AppGloble::mapSizex,
					AppGloble::mapSizey,
					AppGloble::renderSizex,
					AppGloble::renderSizey))
				{
					std::cout<<"fail to create terrian grid"<<std::endl;	

					delete theDA;
					int pp;
					cin>>pp;
					return 0;
				}
			}
		}
		else
		{
			RoamTrianglesCreate(theDA->load_dem_file_avr(AppGloble::mapSizex,AppGloble::mapSizey),
				AppGloble::mapSizex,
				AppGloble::mapSizey,
				AppGloble::renderSizex,
				AppGloble::renderSizey);
		}

	}

	eyeDrawSet();

	glutDisplayFunc(drawModel_terrain);

	glutIdleFunc(drawModel_terrain);

	glutMouseFunc(mouseFunc);

	glutMotionFunc(mouseMotionFunc);

	glutKeyboardFunc(keyFunc);

	glutTimerFunc(500, computFrameRate, 0);

	glutMainLoop();	

	delete theDA;
	int pp;
	cin>>pp;

	return 0;
}
